/* 
 * File:   Nonterminal.cpp
 * Author: itu
 * 
 * Created on November 26, 2011, 9:20 PM
 */

#include "Nonterminal.h"

Nonterminal::Nonterminal(string aSymbol) : Symbol(aSymbol) {
    //cout<<identifier<<endl;
    nullability = false;
    startSymbol = false;
    followSetAlreadyCalculated = false;
    //firstSetAlreadyCalculated = false;
}

void Nonterminal::addRule(Rule newRule) {
    rules.push_back(newRule);
}

Rule Nonterminal::getRule() {
    return rules.back();
}

vector<Rule> Nonterminal::getRules() {
    return rules;
}

bool Nonterminal::hasRule() {
    if (rules.size() > 0)
        return true;
    return false;
}

void Nonterminal::setRules(vector<Rule> newRules) {
    rules = newRules;
}

void Nonterminal::printRules() {
    vector<Rule>::iterator it;
    for (it = rules.begin(); it != rules.end(); ++it) {
        //cout << getIdentifier() << "->";
        it->printSymbols();
        cout << endl;
    }
}

/**
 * Bir nonterminalin ilk kümesini hesaplamak için tüm türetim kuralları incelenir
 * Eğer türetim kuralının ilk sembolü küçük harf ise(terminal) ilk kümesine eklenir
 * Eğer türetim kuralının ilk sembolü büyük harf ise(nonterminal) bu nonterminalin
 * ilk kümesi getirilip tüm elemanları ilk kümesine eklenir. 
 */

void Nonterminal::findFirst() {
    firstSetAlreadyCalculated = true;
    vector<Rule>::iterator it;
    vector<Symbol*> symbols; //kuralların sembollerinin tutmak için kullanılacak
    Nonterminal *nonTerm;
    for (it = rules.begin(); it != rules.end(); ++it) {
        symbols = it->getSymbols();
        if (isupper(symbols[0]->getIdentifier().c_str()[0]) == 0) { //Kuralın ilk elemanı küçük harf(terminal)            
            if (!checkSymbolInFirst(symbols[0]->getIdentifier()))
                firstSet.push_back(symbols[0]);
        } else { //Kuralın ilk elemanı büyük harf(non-terminal)
            //cout<<"ilk eleman: "<<symbols[0]->getIdentifier();
            vector<Symbol*> nonTerminalFirstSet;
            vector<Symbol*>::iterator itt;
            nonTerm = (Nonterminal*) symbols[0];
            nonTerminalFirstSet = nonTerm->getFirstSet();
            //cout<<" First seti: ";
            for (itt = nonTerminalFirstSet.begin(); itt != nonTerminalFirstSet.end(); ++itt) {
                if (!checkSymbolInFirst((*itt)->getIdentifier()))
                    firstSet.push_back(*itt);
                //cout<<"ide: "<<(*itt)->getIdentifier()<<" ";
                //cout<<nonTerminalFirstSet[0]->getIdentifier()<<" ";
            }
        }
    }
}

bool Nonterminal::checkSymbolInFirst(string identifier) {
    bool alreadyInList = false;
    for (int i = 0; i < firstSet.size(); i++) {
        if (identifier.compare(firstSet[i]->getIdentifier()) == 0) {
            alreadyInList = true;
            break;
        }
    }
    return alreadyInList;
}

void Nonterminal::setAsStart() {
    startSymbol = true;
}

void Nonterminal::addToFollow(Symbol *symbol) {
    bool alreadyInList = false;
    //cout<<symbol->getIdentifier()<<" will add to "<<identifier<<endl;
    for (int i = 0; i < followSet.size(); i++) {
        if (symbol->getIdentifier().compare(followSet[i]->getIdentifier()) == 0) {
            alreadyInList = true;
            break;
        }
    }
    if (!alreadyInList)
        followSet.push_back(symbol);
}

void Nonterminal::printFollowSet() {
    for (int i = 0; i < followSet.size(); i++) {
        cout<< followSet[i]->getIdentifier() <<" ";
    }
    cout<<endl;
}

vector<Symbol*> Nonterminal::getFollowSet(){
    return followSet;
}

bool Nonterminal::checkIsStart(){
    return startSymbol;
}

